#pragma once

#include "Noncopyable.h"
#include "Timestamp.h"

#include <functional>
#include <memory>

class EventLoop;// 在源文件中包含头文件，减少信息暴露


/*
*  理清楚 EventLoop、Channel、Poller之间的关系  -》 Reactor模型对应 Demultiplex
*  Channel 理解为通道，封装了sockfd和其感兴趣的event，如EPOLLIN、EPOLLOUT事件
*  还绑定了epoller返回的具体事件
*/

class Channel : noncopyable
{
public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Timestamp)>;

    Channel(EventLoop* loop,int fd);
    ~Channel();

    // fd得到poller通知以后，处理事件的
    void handleEvent(Timestamp receiveTime);

    // 设置回调函数对象
    void setReadCallback(ReadEventCallback cb) { readCallbacke_ = std::move(cb); }
    void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
    void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
    void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }

    // 防止当channel被手动remove掉，channel还在执行后调操作
    void tie(const std::shared_ptr<void>&);

    int fd() const { return fd_; }
    int evevts() const { return events_; }
    int revents(int revt) { revents_ = revt; }

    // 设置fd相应的事件状态 update()：就是通过epoll_ctl -> 添加事件
    void enableReading() { events_ |= kReadEvent; update(); }
    void disableReading() { events_ &= ~kReadEvent; update(); }
    void enableWriting() { events_ |= kWriteEvent; update(); }
    void disableWriting() { events_ &= ~kWriteEvent; update(); }
    void disableAll() { events_ = kNoneEvent; update(); }

    // 返回fd当前的事件状态
    bool isNoneEvent() const { return events_ == kNoneEvent; }
    bool isWriting() const { return events_ == kWriteEvent; }
    bool isReading() const { return events_ == kReadEvent; }

    // 跟业务强相关
    int index() { return index_; }
    void set_index(int idx) { index_ = idx; }

    void set_revents(int revents) { revents_ = revents; }
    // one loop per thread:每个线程一个循环
    EventLoop* ownerLoop() { return loop_; }
    void remove();// 拿来删除channel
private:

    void update();
    void handerEeventWithGuard(Timestamp receiveTime);

    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop *loop_; // 事件循环
    const int fd_;    // fd,Poller监听的的对象
    int events_;      // 注册fd感兴趣的事件
    int revents_;     // poller返回的具体发生事件
    int index_;   

    std::weak_ptr<void> tie_;
    bool tied_;

    // 因为channel通道里面能够获知fd最终当时的具体的事件revents，所以他负责调用具体事件的回调操作
    ReadEventCallback readCallbacke_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};